#include "player.h"

int g_shmid = 0;	//共享内存句柄
int g_start_flag = 0; //开始播放标志位
int g_suspend_flag = 0;//暂停播放标志位 1暂停 0继续
int v = 0;

extern int g_mixerfd;
extern Node *head;
extern int v;

int init_shm(void)
{
	//创建共享内存	IPC_EXCL表示如果这个共享内存已经存在就报错
	g_shmid = shmget(SHMKEY, SHMSIZE, IPC_CREAT | IPC_EXCL);
	if(g_shmid == -1)
	{
		perror("[player.c][init_shm]shmget()");
		return -1;
	}
	
	//映射
	void *addr = shmat(g_shmid, NULL, 0);
	if(addr == (void *)-1)
	{
		perror("[player.c][init_shm]shmat()");
		return -1;
	}
	
	//结构体初始化
	Shm s;
	memset(&s, 0, sizeof(s));	//结构体初始化为0
	s.parent_pid = getpid();
	s.mode = SEQUENCE;			//顺序播放模式
	memcpy(addr, &s, sizeof(s));	//把数据写入共享内存
	
	shmdt(addr);				//解除内存映射
}

int get_shm(Shm *s)
{
	void *addr = shmat(g_shmid, NULL, 0);
	if(addr == (void *)-1)
	{
		perror("[player.c][get_shm]shmat()");
		return -1;
	}
	
	memcpy(s, addr, sizeof(Shm));
	
	shmdt(addr);
}

int set_shm(Shm s)
{
	void *addr = shmat(g_shmid, NULL, 0);
	if(addr == (void *)-1)
	{
		perror("[player.c][get_shm]shmat()");
		return -1;
	}
	
	memcpy(addr, &s, sizeof(Shm));
	
	shmdt(addr);
}

int get_volume(int *v)
{
	// 创建一个文件来存储amixer的输出
    FILE *fp1 = fopen("/tmp/volume.txt", "w+");
    if (fp1 == NULL) {
        perror("fopen");
        return -1;
    }
    
    // 打开管道，通过amixer命令获取音量
    FILE *fp = popen("amixer get Master > /tmp/volume.txt", "w");
    if (fp == NULL) {
        perror("popen");
        return -1;
    }
  
    // 关闭管道
    pclose(fp);
    
    // 打开文件以读取音量数值
    fp = fopen("/tmp/volume.txt", "rb");
    if (fp1 == NULL) {
        perror("fopen");
        fclose(fp);
        return -1;
    }
    
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    size_t bytes_read = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
    fclose(fp);
    
    
    // 解析音量数值
    char *volume_str = strstr(buffer, "Front Left: Playback ");
    if (volume_str != NULL) {
        volume_str += strlen("Front Left: Playback ");
        char *end_ptr = volume_str;
        while (*end_ptr == ' ') {
            end_ptr++;
        }
        *v = atoi(end_ptr);
    } else {
        return -1;
    }
    

    // 删除临时文件
    remove("/tmp/volume.txt");
}

void get_music(const char *singer)
{
	//发送请求
	struct json_object *obj = (struct json_object *)json_object_new_object();
	json_object_object_add(obj, "cmd", json_object_new_string("get_music_list"));
	json_object_object_add(obj, "singer", json_object_new_string(singer));
	
	socket_send_data(obj);
	
	char msg[1024] = {0};
	socket_recv_data(msg);
	
	//形成链表
	creat_link(msg);
	
	//上传音乐数据
	upload_music_list();
	
	json_object_put(obj);
}

int start_play()
{
	if(g_start_flag == 1)	//0初始状态还没播放	  1播放中不能重复播放
		return -1;
	
	if(head->next == NULL)
		return -1;
	
	char name[32] = {0};
	strcpy(name, head->next->music_name);
	
	//初始化音量
	v = 30;
	//将变量v转换为字符串
	char command[50];
	snprintf(command, sizeof(command), "./volume_set.sh %d", v);
	system(command);
	
	g_start_flag = 1;		//播放中  ，stop_play函数置回0可重新开始播放
	
	play_music(name);
	
	return 0;
}

/*子进程收到SIGUSR2信号，触发该函数*/
void child_quit()
{
	g_start_flag = 0;
}

void play_music(char *n)
{
	pid_t child_pid = fork();
	if(child_pid == -1)
	{
		perror("[player.c][play_music]fork()");
		return;
	}
	else if(child_pid == 0)		//子进程
	{
		//close(0);			//关闭标准输入，留给select.c的进程使用
		signal(SIGUSR2, child_quit);
		child_process(n);
		exit(0);
	}
	
	else	//父进程	回收子进程放在[link.c][update_music()]
	{
		return;
	}
}

/*子进程：
1、创建孙进程，调用mplayer播放音乐
2、等待孙进程结束
*/
void child_process(char *n)
{
	while(g_start_flag)
	{
		pid_t grand_pid = fork();
		if(grand_pid == -1)
		{
			perror("[player.c][child_process]fork()");
			return;
		}
		else if(grand_pid == 0)		//孙进程
		{
			//close(0);				//关闭标准输入
			Shm s;
			memset(&s, 0, sizeof(s));
			
			if(strlen(n) == 0)		//第二次进入循环（自动播放下一首）
			{
				grand_get_shm(&s);	//获取共享内存数据
				
				if(find_next_music(s.cur_music, s.mode, n) == -1)	//在link.c
				{
					//歌曲播放完了，通知父进程和子进程
					kill(s.parent_pid, SIGUSR1);
					kill(s.child_pid, SIGUSR2);		//把g_start_flag置0	
					usleep(100000);		//100ms,确保发出通知
					exit(0);
				}
				
			}
			//char*arg[7] = {0};
			char music_path[128] = {0};
			
			strcpy(music_path, URL);
			strcat(music_path, n);
			/*		
			arg[0] = "mplayer";
			arg[1] = music_path;
			arg[2] = "-slave";
			arg[3] = "-quiet";
			arg[4] = "-input";
			arg[5] = "file=./cmd_fifo";
			arg[6] = NULL;		//不要加双引号
			*/
			
			// 设置参数数组
			char *arg[] = {
			    "mplayer",           // mplayer 程序名
			    music_path,          // 音乐文件路径
			    "-slave",            // 作为 slave 运行
			    "-quiet",            // 减少详细输出
			    "-input",            // 设置输入选项
			    "file=./cmd_fifo",   // 输入文件
			    NULL                 // 参数列表结束
			};
			
			//修改共享内存（子进程 孙进程id  音乐名字）
			grand_get_shm(&s);
			char *p = n;
			while(*p != '/')		//取斜杠后的名字，方大同/小小虫.mp3
				p++;
			strcpy(s.cur_music, p +1);
			grand_set_shm(s);
			printf("dddddd:%s\n",s.cur_music);		
			
#ifdef ARM	
			execv("/bin/mplayer", arg);
#else			
			execv("/usr/bin/mplayer", arg);
#endif			
		}
		else						//子进程
		{
			memset(n, 0, sizeof(n));
			int status;
			wait(&status);
			
			usleep(100000);
		}
	}
}

void grand_set_shm(Shm s)
{
	//修改共享内存（子进程 孙进程id  音乐名字）
	int shmid = shmget(SHMKEY, SHMSIZE, 0);		//给0获取共享内存
	if(shmid == -1)
	{
		perror("grand shmget");
		return;
	}
	
	void *addr = shmat(shmid, NULL, 0);
	if(addr == (void *)-1)
	{
		perror("grand shmat");
		return;
	}
	
	s.child_pid = getppid();
	s.grand_pid = getpid();
	
	memcpy(addr, &s, sizeof(s));
	
	shmdt(addr);
}

void grand_get_shm(Shm *s)
{
	int shmid = shmget(SHMKEY, SHMSIZE, 0);		//给0获取共享内存
	if(shmid == -1)
	{
		perror("grand shmget");
		return;
	}
	
	void *addr = shmat(shmid, NULL, 0);
	if(addr == (void *)-1)
	{
		perror("grand shmat");
		return;
	}
	
	memcpy(s, addr, sizeof(Shm));
	
	shmdt(addr);
}

void write_fifo(const char *cmd)
{
	int fd = open("cmd_fifo", O_WRONLY);
	if(fd == -1)
	{
		perror("[player.c][write_fifo]open()");
	}
	
	if(write(fd, cmd, strlen(cmd)) == -1)
	{
		perror("[player.c][write_fifo]write()");
	}
	
	close(fd);
}

void stop_play()
{
	if(g_start_flag == 0)
		return;
	//通知子进程
	Shm s;
	get_shm(&s);
	kill(s.child_pid, SIGUSR2);
	
	//结束mplayer进程
	write_fifo("quit\n");
	
	//回收子进程
	int status;
	waitpid(s.child_pid, &status, 0);
	
	g_start_flag = 0;	//主进程start_play函数g_start_flag置了1，要给回0才能开始播放
}

void suspend_play()
{
	if(g_start_flag == 0 || g_suspend_flag == 1) //没播放或暂停中
		return;
	printf("-- 暂停播放 --\n");
	
	write_fifo("pause\n");
	
	g_suspend_flag = 1;
}

void continue_play()
{
	if(g_start_flag == 0 || g_suspend_flag == 0)
		return;
	
	printf("-- 继续播放 --\n");
	
	write_fifo("pause\n");
	
	g_suspend_flag = 0;
}

void next_play()
{
	if(g_start_flag == 0)
		return;
	
	Shm s;
	get_shm(&s);
	char music[128] = {0};
	if(find_next_music(s.cur_music, SEQUENCE, music) == -1)
	{
		//链表里的歌曲播放完了
		stop_play();
		
		char singer[128] = {0};
		get_singer(singer);
		
		clear_link();
		get_music(singer);
		sleep(1);
		
		start_play();
		
		if(g_suspend_flag == 1)
			g_suspend_flag = 0;
		
		return;
	}
	
	char path[256] = {0};
	strcat(path, URL);
	strcat(path, music);
	
	char cmd[1024] = {0};
	sprintf(cmd, "loadfile %s\n", path);
	
	write_fifo(cmd);
	
	//更新共享内存，不然只能一直播一首
	int i;
	for(i = 0; i < sizeof(music); i++)
	{
		if(music[i] == '/')
			break;
	}
	strcpy(s.cur_music, music + i + 1);
	set_shm(s);
	
	if(g_suspend_flag == 1)
	{
		g_suspend_flag = 0;
	}
}

void prior_play()
{
	if(g_start_flag == 0)
		return;
	
	Shm s;
	get_shm(&s);
	char music[128] = {0};
	find_prior_music(s.cur_music, music);
	
	char path[256] = {0};
	strcat(path, URL);
	strcat(path, music);
	
	char cmd[1024] = {0};
	sprintf(cmd, "loadfile %s\n", path);
	
	write_fifo(cmd);
	
	//更新共享内存，不然只能一直播一首
	int i;
	for(i = 0; i < sizeof(music); i++)
	{
		if(music[i] == '/')
			break;
	}
	strcpy(s.cur_music, music + i + 1);
	set_shm(s);
	
	if(g_suspend_flag == 1)
		g_suspend_flag = 0;
}

void voice_up()
{
	
	if(v <= 95)
	{
		v += 5;
	}
	else{
		printf("音量已经最大\n");
		return;
	}

	//将变量v转换为字符串
	char command[50];
	snprintf(command, sizeof(command), "./volume_set.sh %d", v);
	system(command);
	/*
	int v;
	get_volume(&v);
	
	if(v <= 60)
	{
		v += 3;
	}
	else{
		printf("音量已经最大\n");
		return;
	}
	
	// 创建一个文件来存储amixer的输出
    FILE *fp1 = fopen("/tmp/null", "w+");
    if (fp1 == NULL) {
        perror("[player.c][start_play]fopen()");
        return;
    }
	
	//将变量v转换为字符串
	char command[50];
	snprintf(command, sizeof(command), "amixer set -c 0 Master %d > /tmp/null", v);
	
	// 设置音量
    FILE *fp = popen(command, "w");
    if (fp == NULL) {
        perror("[player.c][start_play]popen()");
        return;
    }
	// 确保amixer命令的输出被发送到音频混合器
    pclose(fp);
    fclose(fp1);*/
	
	printf("-- 增加音量 --\n");
}

void voice_down()
{
	if(v >= 5)
	{
		v -= 5;
	}
	else{
		printf("音量已经最小\n");
		return;
	}
	//将变量v转换为字符串
	char command[50];
	snprintf(command, sizeof(command), "./volume_set.sh %d", v);
	system(command);
	
	/*
	int v;
	get_volume(&v);
	
	if(v >= 3)
	{
		v -= 3;
	}
	else{
		printf("音量已经最小\n");
		return;
	}
	
	// 创建一个文件来存储amixer的输出
    FILE *fp1 = fopen("/tmp/null", "w+");
    if (fp1 == NULL) {
        perror("[player.c][start_play]fopen()");
        return;
    }
	
	//将变量v转换为字符串
	char command[50];
	snprintf(command, sizeof(command), "amixer set -c 0 Master %d > /tmp/null", v);
	
	// 设置音量
    FILE *fp = popen(command, "w");
    if (fp == NULL) {
        perror("[player.c][start_play]popen()");
        return;
    }
	// 确保amixer命令的输出被发送到音频混合器
    pclose(fp);
    fclose(fp1);*/
	
	printf("-- 减小音量 --\n");
}


void circle_play()
{
	Shm s;
	get_shm(&s);
	s.mode = CIRCLE;
	set_shm(s);
	printf("-- 单曲循环 --\n");
}

void sequence_play()
{
	Shm s;
	get_shm(&s);
	s.mode = SEQUENCE;
	set_shm(s);
	printf("-- 顺序循环 --\n");
}

void singer_play(const char *singer)
{
	//停止播放
	stop_play();
	
	//清空链表
	clear_link();
	
	//获取歌曲
	get_music(singer);
	
	//开始播放
	start_play();
}
